package vt.mangum;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Environment;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ToggleButton;

public class KeyloggerActivity extends Activity 
{
	
	private final static int LOG_TYPE_LETTER = 0;
	private final static int LOG_TYPE_CONTINUOUS = 1;

	private float deltaX, deltaY, deltaZ, mLastX, mLastY, mLastZ;
	private boolean mInitialized, mIsOn, mExists, mWrite;
	private Spinner speedSelectSpinner, logSelectSpinner;
	private Sensor sensor;
	private SensorManager sensorManager;
	private TextView xview, yview, zview;
	private EditText input;
	private ToggleButton toggle;
	private final float NOISE = (float) 0.0;
	private int speed = SensorManager.SENSOR_DELAY_GAME;
	private int logType;
	private String path = null;
	private File f, root, fX, fY, fZ;
	
    /** 
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mInitialized = false;
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        
        //////////////////////////////
        //Setting up the file output//
        //////////////////////////////
        
		String state = Environment.getExternalStorageState();
		if (Environment.MEDIA_MOUNTED.equals(state)) {
		    // We can read and write the media
		    mExists = mWrite = true;
		} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
		    // We can only read the media
		    mExists = true;
		    mWrite = false;
		} else {
		    // Something else is wrong. It may be one of many other states, but all we need
		    //  to know is we can neither read nor write
		    mExists = mWrite = false;
		}
		
		if(mExists && mWrite){

			path = Environment.getExternalStorageDirectory() + "/Magnum/";
			root = new File(path);
			root.mkdirs();
			fX = new File(root, "Xgraph.txt");
			fY = new File(root, "Ygraph.txt");
			fZ = new File(root, "Zgraph.txt");
			f = new File(root, "keys.txt");
			
			if(!f.exists()){
				try {
					f.createNewFile();
					} catch (IOException e) {
						Log.e("File Creation", "Could not write file: " + e.getMessage());
				}
			}
			else{
				try{
					FileWriter writer = new FileWriter(f);
					BufferedWriter out = new BufferedWriter(writer);
					out.write("");
					out.close();
					
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());
					
				}
	
			}
			if(!fX.exists()){
				try {
					fX.createNewFile();
					} catch (IOException e) {
						Log.e("File Creation", "Could not write file: " + e.getMessage());
				}
			}
			else{
				try{
					FileWriter writer = new FileWriter(fX);
					BufferedWriter out = new BufferedWriter(writer);
					out.write("");
					out.close();
					
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());
					
				}
	
			}
			if(!fY.exists()){
				try {
					fY.createNewFile();
					} catch (IOException e) {
						Log.e("File Creation", "Could not write file: " + e.getMessage());
				}
			}
			else{
				try{
					FileWriter writer = new FileWriter(fY);
					BufferedWriter out = new BufferedWriter(writer);
					out.write("");
					out.close();
					
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());
					
				}
	
			}
			if(!fZ.exists()){
				try {
					fZ.createNewFile();
					} catch (IOException e) {
						Log.e("File Creation", "Could not write file: " + e.getMessage());
				}
			}
			else{
				try{
					FileWriter writer = new FileWriter(fZ);
					BufferedWriter out = new BufferedWriter(writer);
					out.write("");
					out.close();
					
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());
					
				}
	
			}
		}
			        
        input = (EditText) findViewById(R.id.editText1);
        input.addTextChangedListener(new TextWatcher(){
            public void afterTextChanged(Editable s) {}
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(mExists && mWrite && mIsOn && count >= 1){
                	try{
                		FileWriter out = new FileWriter(f, true);
                		if(logType == LOG_TYPE_LETTER){
                			out.append(s.charAt(count-1) + " - X: " + deltaX + ", Y: " + deltaY + ", Z: " + deltaZ + "\n");
                		}
                		else if(logType == LOG_TYPE_CONTINUOUS){
                			out.append(s.charAt(count-1) + "\n");
                		}
                		out.flush();
                		out.close();
                		
                	} catch (IOException e) {
                		Log.e("File Write", "Could not write to file: " + e.getMessage());
                 	}
                }
			}

        });
        
        logSelectSpinner = (Spinner) findViewById(R.id.logSpinner);
        ArrayAdapter<CharSequence> logAdapter = ArrayAdapter.createFromResource(
        		this, R.array.log_array, android.R.layout.simple_spinner_item);
        logAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        logSelectSpinner.setAdapter(logAdapter);
        logSelectSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

			@Override
			public void onItemSelected(AdapterView<?> parent, View view,
					int pos, long id) {
				
				switch(pos){
				case(0):	logType = LOG_TYPE_LETTER;
				case(1):	logType = LOG_TYPE_CONTINUOUS;

			}
				
				if(mIsOn){
					sensorManager.unregisterListener(sel);
			        sensorManager.registerListener(sel, sensor, speed);
				}
				
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				//Do Nothing.
				
			}
        	
        });

        
        speedSelectSpinner = (Spinner) findViewById(R.id.speedSpinner);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this, R.array.speed_array, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        speedSelectSpinner.setAdapter(adapter);
        speedSelectSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

			@Override
			public void onItemSelected(AdapterView<?> parent, View view,
					int pos, long id) {
				switch(pos){
					case(0):	speed = SensorManager.SENSOR_DELAY_FASTEST;
					case(1):	speed = SensorManager.SENSOR_DELAY_GAME;
					case(2):	speed = SensorManager.SENSOR_DELAY_NORMAL;
					case(3):	speed = SensorManager.SENSOR_DELAY_UI;
				}
				
				if(mIsOn){
					sensorManager.unregisterListener(sel);
			        sensorManager.registerListener(sel, sensor, speed);
				}
				
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				//Do nothing.
				
			}
        	
        });
        
        toggle = (ToggleButton) findViewById(R.id.toggle);
        toggle.setChecked(false);
        toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
				if(arg1 == false){
					mIsOn = false;
					sensorManager.unregisterListener(sel);
				}
				else{
					mIsOn = true;
			        sensorManager.registerListener(sel, sensor, speed);
				}
				
			}
        	
        });
        xview = (TextView) findViewById(R.id.x);
        yview = (TextView) findViewById(R.id.y);
        zview = (TextView) findViewById(R.id.z);
    }
    

    private void display()
    {
    	String xstring = String.format("x is: %f", deltaX);
    	String ystring = String.format("y is: %f", deltaY);
    	String zstring = String.format("z is: %f", deltaZ);
		xview.setText(xstring);
		yview.setText(ystring);
		zview.setText(zstring);
		
		if(logType == LOG_TYPE_CONTINUOUS){
			//Log The data here.
		}
    }
    
    
    /**
     * Called when the activity is becoming visible to the user.
     */
    @Override
    protected void onResume()
    {
    	super.onResume();
    	if(mIsOn){
    		sensorManager.registerListener(sel, sensor, speed);
    	}

    }
    
    /**
     * Called when the activity is no longer visible to the user.
     */
    @Override
    protected void onStop()
    {
    	sensorManager.unregisterListener(sel);
		super.onStop();
    }
    
    /**
     * Instantiates a new SensorEventLister object.
     */
    private SensorEventListener sel = new SensorEventListener() 
    {
    	
    	/**
    	 * Called when the accuracy of a sensor has changed.
    	 */
		@Override
		public void onAccuracyChanged(Sensor s, int acc) 
		{
			return;
		}
 
		/**
		 * Called when sensor values have changed.
		 */
		@Override
		public void onSensorChanged(SensorEvent event) 
		{
			
			float x = event.values[0];
			float y = event.values[1];
			float z = event.values[2];
			if (!mInitialized) {
				mLastX = x;
				mLastY = y;
				mLastZ = z;
				xview.setText("x is: 0.0");
				yview.setText("y is: 0.0");
				zview.setText("z is: 0.0");
				mInitialized = true;
			} else {
				deltaX = Math.abs(mLastX - x);
				deltaY = Math.abs(mLastY - y);
				deltaZ = Math.abs(mLastZ - z);
				if (deltaX < NOISE) deltaX = (float)0.0;
				if (deltaY < NOISE) deltaY = (float)0.0;
				if (deltaZ < NOISE) deltaZ = (float)0.0;
				mLastX = x;
				mLastY = y;
				mLastZ = z;
			}
			
			//Log Continuous
			if(mExists && mWrite && logType == LOG_TYPE_CONTINUOUS){

				
				try{
					FileWriter xWriter = new FileWriter(fX, true);
					xWriter.append(deltaX + ", ");
					xWriter.flush();
					xWriter.close();
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());		
				}
				try{
					FileWriter yWriter = new FileWriter(fY, true);
					yWriter.append(deltaY + ", ");
					yWriter.flush();
					yWriter.close();
					
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());
						
				}
		

				try{
					FileWriter zWriter = new FileWriter(fZ, true);
					zWriter.append(deltaZ + ", ");
					zWriter.flush();
					zWriter.close();
					
				} catch (IOException e) {
					Log.e("File Creation", "Could not write file: " + e.getMessage());
					
				}
	
			}
			display();
		}

	};

	
}